/**
 * @fileoverview
 * This script defines a widget for fetching and displaying images from www.fly-ted.org.
 * @author <a href="http://purl.org/net/aliman">Alistair Miles</a>, Graham Klyne, Jun Zhao
 * @version $Revision:538 $ on $Date: 2008-08-27 09:08:41 +0100 (Wed, 27 Aug 2008) $ by $Author: aliman $
 * @requires YAHOO.util.Connect
 * @requires flyui
 * @requires flyui.flyted.Service
 * TODO license terms
 */
 
// create a namespace if not already defined
flyui.namespace("flyui.flyted");


/**
 * TODO doc me
 * @class
 * @constructor
 * @param {flyui.flyted.Service} service the service to use to fetch data
 * @param {flyui.flyted.DefaultRenderer} renderer the renderer to use
 */
flyui.flyted.ImageWidget = function( service, renderer ) {

	var that = this;
	
	/** @private */
	this._controller = null;
	
	/**
	 * TODO doc me
	 * @private
	 */
	this._init = function() {
		// create a model
		var model = new flyui.mvcutils.GenericModel(flyui.flyted.ImageWidget.modelDefinition);
		
		// instantiate the controller
		this._controller = new flyui.flyted.ImageWidget.Controller(model, service, this);
		
		// connect the renderer to the model
		renderer.connect(model);
	};
	
	// do initialisation
	this._init();
	
};


/**
 * TODO doc me
 * @param {String} flytedGeneName a flyted gene name, see http://www.fly-ted.org/view/geneid/
 */
flyui.flyted.ImageWidget.prototype.findImagesByFlytedGeneName = function( flytedGeneName ) {
	// pass through to controller
	this._controller.findImagesByFlytedGeneName(flytedGeneName);
};


/**
 * TODO doc me
 * @param {String} flybaseGeneID a flybase gene ID, e.g. FBgn123456
 */
flyui.flyted.ImageWidget.prototype.findImagesByFlybaseGeneID = function( flybaseGeneID ) {
	// pass through to controller
	this._controller.findImagesByFlybaseGeneID(flybaseGeneID);
};


/**
 * TODO doc me
 * @class
 * @constructor
 * @param {flyui.mvcutils.GenericModel} model the model to store widget state data
 * @param {flyui.flyted.Service} service the service to use to fetch data
 * @param {flyui.flyted.ImageWidget} widget the widget to control
 */
flyui.flyted.ImageWidget.Controller = function( model, service, widget ) {
	
	var that = this;
	
	/**
	 * @private
	 */
	this._model = model;
	
	/**
	 * @private
	 */
	this._service = service;
	
	/**
	 * @private
	 */
	this._parent = widget;
	
	
	/**
	 * @private
	 */	
	this._findImagesSuccess = function( images ) {
		log("request success");
		
		// set the results
		that._model.set("RESULTS", images);
		
		// set the state
		that._model.set("STATE", "READY");

	};
	
	
	/**
	 * @private
	 */	
	this._findImagesFailure = function( response ) {

		log("request failed, status "+response.status+" "+response.statusText, "error");
		
		// set an error message
		var msg = "There was an error retrieving data from FlyTED, see the logs for more info. The server may be busy or down, please try again later. If this message persists, please contact the Image Bioinformatics Research Group at bioimage@mail.ontonet.org.";		

		that._model.set("ERRORMESSAGE", msg);

		// set the state
		that._model.set("STATE", "SERVERERROR");		
	};
	
	
	/**
	 * @private
	 */	
	this._findImagesByFlytedGeneNameSuccess = function( images ) {

		// call the success callback
		that._findImagesSuccess(images);
		
	};
	
	/**
	 * @private
	 */	
	this._findImagesByFlytedGeneNameFailure = function( response ) {
		
		// call the failure callback		
		that._findImagesFailure(response);

	};

	/**
	 * @private
	 */
	 
	this._findImagesByFlybaseGeneIDSuccess = function ( images ) {
		// call the success callback
		that._findImagesSuccess(images);
	}
	
	/**
	 * @private
	 */
	this._findImagesByFlybaseGeneIDFailure = function ( response ) {
		
		// call the failure callback		
		that._findImagesFailure(response);
	}
};


/**
 * TODO doc me
 * @param {String} flytedGeneName a flyted gene name, see http://www.fly-ted.org/view/geneid/
 */
flyui.flyted.ImageWidget.Controller.prototype.findImagesByFlytedGeneName = function( flytedGeneName ) {
	// pass through to private implementation
	this._findImagesByFlytedGeneName(flytedGeneName, this._findImagesByFlytedGeneNameSuccess, this._findImagesByFlytedGeneNameFailure);
};


/**
 * TODO doc me
 */
flyui.flyted.ImageWidget.Controller.prototype._findImagesByFlytedGeneName = function( flytedGeneName, success, failure ) {

	log("flyui.flyted.ImageWidget.Controller._findImagesByFlytedGeneName :: request: "+flytedGeneName);
	
	// set the model pending
	this._model.set("STATE", "PENDING");
	
	// set the query property
	this._model.set("QUERY", flytedGeneName);
	
	// kick off the request
	this._service.findImagesByFlytedGeneName(flytedGeneName, success, failure);
};


/**
 * TODO doc me
 * @param {String} flybaseGeneID a flybase gene ID, e.g. FBgn123456
 */
flyui.flyted.ImageWidget.Controller.prototype.findImagesByFlybaseGeneID = function( flybaseGeneID ) {
	// pass through to private implementation
	this._findImagesByFlybaseGeneID(flybaseGeneID, this._findImagesByFlybaseGeneIDSuccess, this._findImagesByFlybaseGeneIDFailure);
};


/**
 * TODO doc me
 * @private
 * @param {String} flybaseGeneID a flybase gene ID, e.g. FBgn123456
 */
flyui.flyted.ImageWidget.Controller.prototype._findImagesByFlybaseGeneID = function( flybaseGeneID, success, failure ) {
	log("flyui.flyted.ImageWidget.Controller._findImagesByFlybaseGeneID :: request: "+flybaseGeneID);
	
	// set the model pending
	this._model.set("STATE", "PENDING");
	
	// set the query property
	this._model.set("QUERY", flybaseGeneID);
	
	// kick off the request
	this._service.findImagesByFlybaseGeneID(flybaseGeneID, success, failure);
};


/**
 * TODO doc me
 */
flyui.flyted.ImageWidget.modelDefinition = {

	propertyNames : [ "STATE", "RESULTS", "QUERY", "ERRORMESSAGE" ],
	
	controlledValues : {
		"STATE" : [ "PENDING", "READY", "SERVERERROR", "UNEXPECTEDERROR" ]
	},
	
	initialize : function( data ) {
		data["STATE"] = "READY";
		data["RESULTS"] = null;
		data["QUERY"] = null;
		data["ERRORMESSAGE"] = null;
	}

};


/**
 * TODO doc me
 * @class
 * @constructor
 */
flyui.flyted.ImageWidget.DefaultRenderer = function( renderPane ) {
	
	var that = this;
	
	/** @private */
	this._containerPane = renderPane;
	
	/**
	 * @private
	 */
	this._onStateChanged = function( oldState, newState ) {
		if ( newState == "PENDING" ) {
			flyui.mvcutils.show(that._pendingPane);
			flyui.mvcutils.hide(that._messagePane);
			flyui.mvcutils.hide(that._resultsSummaryPane);
			flyui.mvcutils.hide(that._resultsPane);
		} 
		else if (newState == "READY") {
			flyui.mvcutils.hide(that._pendingPane);
			flyui.mvcutils.hide(that._messagePane);
			flyui.mvcutils.show(that._resultsSummaryPane);
			flyui.mvcutils.show(that._resultsPane);		
		}
		else if ( newState == "SERVERERROR" || newState == "UNEXPECTEDERROR" ) {
			flyui.mvcutils.hide(that._pendingPane);
			flyui.mvcutils.show(that._messagePane);
			flyui.mvcutils.hide(that._resultsSummaryPane);
			flyui.mvcutils.hide(that._resultsPane);			
		} 
		else {
			// this should never happen
			throw {name:"flyui.flyted.ImageWidget.UnexpectedStateError", message:"Invalid state: "+newState};
		}
	};

	/**
	 * @private
	 */
	this._onQueryChanged = function( oldQuery, newQuery ) {
		that._resultsSummaryQueryPane.innerHTML = newQuery;
		that._resultsSummaryCountPane.innerHTML = "this should never be displayed";
	};
	
	
	/**
	 * @private
	 */
	this._onResultsChanged = function( oldResults, newResults ) {
		// set the count in the summary
		that._resultsSummaryCountPane.innerHTML = newResults.length;
		
		if (newResults.length > 0) {
			
			// set the content
			that._resultsPane.innerHTML = flyui.flyted.ImageWidget.DefaultRenderer.imagesToDivHTML(newResults);	

		}
		else {
			that._resultsPane.innerHTML = "";
		}
	};
	
	
	/**
	 * @private
	 */
	this._onErrorMessageChanged = function( oldMsg, newMsg) {
		that._messagePane.innerHTML = newMsg;
	};
	
	
	/**
	 * @private
	 */
	this._init = function() {
		
		// set up the pending pane
		this._pendingPane = document.createElement("div");
		this._pendingPane.innerHTML = "<p>Pending...</p>";
		this._containerPane.appendChild(this._pendingPane);
		flyui.mvcutils.hide(this._pendingPane);
		
		// set up the message pane
		this._messagePane = document.createElement("div");
		this._messagePane.innerHTML = "this should never be displayed";
		this._containerPane.appendChild(this._messagePane);
		flyui.mvcutils.hide(this._messagePane);
		
		// setup results summary pane
		this._resultsSummaryPane = document.createElement("div");
		this._containerPane.appendChild(this._resultsSummaryPane);
		flyui.mvcutils.hide(this._resultsSummaryPane);
		
		// set up results summary content
		this._resultsSummaryCountPane = document.createElement("span");
		this._resultsSummaryCountPane.innerHTML = "this should never be displayed";
		this._resultsSummaryQueryPane = document.createElement("span");
		this._resultsSummaryQueryPane.innerHTML = "this should never be displayed";
		this._resultsSummaryPane.appendChild(document.createTextNode("Found "));
		this._resultsSummaryPane.appendChild(this._resultsSummaryCountPane);
		this._resultsSummaryPane.appendChild(document.createTextNode(" images for query \""));
		this._resultsSummaryPane.appendChild(this._resultsSummaryQueryPane);
		this._resultsSummaryPane.appendChild(document.createTextNode("\""));
		
		// setup results pane
		this._resultsPane = document.createElement("div");
		this._containerPane.appendChild(this._resultsPane);
		flyui.mvcutils.hide(this._resultsPane);

	};
	
	// do initialisation
	this._init();
	
};


/**
 * TODO doc me
 */
flyui.flyted.ImageWidget.DefaultRenderer.prototype.connect = function( model ) {
	model.addListener("STATE", this._onStateChanged);
	model.addListener("QUERY", this._onQueryChanged);
	model.addListener("RESULTS", this._onResultsChanged);
	model.addListener("ERRORMESSAGE", this._onErrorMessageChanged);
};


/**
 * TODO doc me
 */
flyui.flyted.ImageWidget.DefaultRenderer.imagesToDivHTML = function( images ) {
	
	// build the divs
	
	var content = "";
	for ( var i in images ) {
		
		content += flyui.flyted.ImageWidget.DefaultRenderer.imageToDivHTML(images[i]);
		log ("Generate the img div" + content, "test");	
	}
	
	return content;
};


/**
 * TODO doc me
 */
flyui.flyted.ImageWidget.DefaultRenderer.imageToDivHTML = function( image ) {
 	
 	//TODO include the caption
 	
 	var content = 	"<div class=\"result\">";
	content +=			"<a href=\"" + image.flytedURL + "\">";
	content +=				"<img src=\"" + image.thumbnailURL + "\" alt=\"this is an image\">";
	content +=			"</img></a>"; 
	content +=			"<p>"+image.caption+"</p>"
	content +=		"</div>";
	
	return content;
};